package com.piggy.flowable.factory;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.piggy.common.core.constant.FlowableRedisKeyEnums;
import com.piggy.common.redis.cache.CacheUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.engine.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.*;

/**
 * flowable 引擎注入封装
 * @author XuanXuan
 * @date 2021-04-03
 */
@Slf4j
@Component
@Getter
public class FlowServiceFactory {

    @Resource
    protected RepositoryService repositoryService;

    @Resource
    protected RuntimeService runtimeService;

    @Resource
    protected IdentityService identityService;

    @Resource
    protected TaskService taskService;

    @Resource
    protected FormService formService;

    @Resource
    protected HistoryService historyService;

    @Resource
    protected ManagementService managementService;

    @Qualifier("processEngine")
    @Resource
    protected ProcessEngine processEngine;

    protected final static BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
    protected final static BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter();

    protected void parseCustomAttr(String processDefId) {
        XMLStreamReader reader = null;

        try {
            InputStream inputStream = repositoryService.getProcessModel(processDefId);
            XMLInputFactory factory = XMLInputFactory.newInstance();
            reader = factory.createXMLStreamReader(inputStream);
            BpmnModel bpmnModel = bpmnXMLConverter.convertToBpmnModel(reader);
            List<Process> processes = bpmnModel.getProcesses();
            if (CollUtil.isEmpty(processes)) {
                log.error("BPMN模型没有配置流程");
                return ;
            }
            Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
            Map<String, Map<String,Object>> attributes = new LinkedHashMap<>();
            if (CollUtil.isEmpty(flowElements)) {
                return ;
            }

            flowElements.forEach(item-> {

                log.info("class = {}, element = {}", item.getClass(), JSON.toJSONString(item));

                List<ExtensionElement> extensionElements = new ArrayList<>();
                if (CollUtil.isNotEmpty(item.getExtensionElements())) {
                    if (item.getExtensionElements().containsKey("properties")) {
                        if (CollUtil.isNotEmpty(item.getExtensionElements().get("properties"))) {
                            item.getExtensionElements().get("properties").forEach(item1-> {
                                if (CollUtil.isNotEmpty(item1.getChildElements()) && item1.getChildElements().containsKey("property")) {
                                    extensionElements.addAll(item1.getChildElements().get("property"));
                                }
                            });
                        }
                    }
                }

                if (CollUtil.isNotEmpty(extensionElements)) {
                    attributes.put(item.getId(), new HashMap<>());
                    extensionElements.forEach(item1-> {
                        String name = null,value=null;
                        if (CollUtil.isNotEmpty(item1.getAttributes()) && CollUtil.isNotEmpty(item1.getAttributes().get("name"))) {
                            name = item1.getAttributes().get("name").get(0).getValue();
                        }
                        if (CollUtil.isNotEmpty(item1.getAttributes()) && CollUtil.isNotEmpty(item1.getAttributes().get("value"))) {
                            value = item1.getAttributes().get("value").get(0).getValue();
                        }
                        if (StrUtil.isNotBlank(name) && StrUtil.isNotBlank(value)) {
                            attributes.get(item.getId()).put(name,value);
                        }
                    });
                }
            });

            if (CollUtil.isNotEmpty(attributes)) {
                String key = FlowableRedisKeyEnums.CustomAttr.getKey(processDefId);
                CacheUtils.cache(attributes, key);
                log.info("attr = {}", JSON.toJSONString(attributes));
            }

        } catch (Exception e) {
            log.error("BPMN模型创建流程异常", e);
            return;
        } finally {
            try {
                Objects.requireNonNull(reader).close();
            } catch (XMLStreamException e) {
                log.error("关闭异常", e);
            }
        }
    }
}
